/*
 * UString.h
 *
 *  Created on: 2020年3月24日
 *      Author: chuanjiang.zh
 */

#ifndef USTRING_H_
#define USTRING_H_

#include "BasicType.h"
#include <string>

class UStringPrivate;

class DLLEXPORT UString
{
public:
	UString();
	virtual ~UString();

    UString(const char* str);
	UString(const char* str, size_t length);
	UString(const UString& other);

	explicit UString(size_t length);
	UString(size_t num, const char& ch);

	UString& operator = (const char* str);
	UString& operator = (const UString& other);
	UString& operator = (char ch);


	UString& assign(size_t num, const char& ch);
	UString& assign(const UString& other);
	UString& assign(const char* str);
	UString& assign(const char* str, size_t length);


	void swap(UString& other);


    size_t size() const;
	size_t length() const;
	size_t capacity() const;
	size_t max_size() const;
	bool empty() const;

	char& at(size_t idx);
	const char& at(size_t idx) const;

	const char* c_str() const;
	const char* data() const;
	char* data();


	char& operator[](size_t idx);
	const char& operator[] (size_t idx) const;

	bool operator == (const UString& other) const;
	bool operator != (const UString& other) const;
	bool operator < (const UString& other) const;
	bool operator <= (const UString& other) const;
	bool operator > (const UString& other) const;
	bool operator >= (const UString& other) const;

	bool operator == (const char* str) const;
	bool operator != (const char* str) const;
	bool operator < (const char* str) const;
	bool operator <= (const char* str) const;
	bool operator > (const char* str) const;
	bool operator >= (const char* str) const;

	int compare(const char* str) const;
	int compare(const UString& other) const;

	UString operator + (char ch);
	UString operator + (const char* str);
	UString operator + (const UString& other);

	UString& operator += (char ch);
	UString& operator += (const char* str);
	UString& operator += (const UString& other);


	UString& append(size_t num, char ch);
	UString& append(const char* str);
	UString& append(const char* str, size_t length);
	UString& append(const UString& other);

	UString& insert(size_t idx, size_t num, char ch);
	UString& insert(size_t idx, const char* str);
	UString& insert(size_t idx, const char* str, size_t length);
	UString& insert(size_t idx, const UString& other);

	UString& replace(size_t idx, size_t num, const char* str);
	UString& replace(size_t idx, size_t num, const char* str, size_t length);
	UString& replace(size_t idx, size_t num, const UString& other);

	void reserve(size_t length);

	void resize(size_t length, char ch = 0);

	UString& erase(size_t idx, size_t num = std::string::npos);

	void clear();

	size_t copy(char* buffer, size_t length, size_t fromIdx) const;

	size_t find(const UString& other, size_t idx=0) const;
	size_t find(const char* str, size_t idx=0) const;
	size_t find(const char* str, size_t idx, size_t length) const;
	size_t find(char ch, size_t idx=0) const;

	size_t rfind(const UString& other, size_t idx=std::string::npos) const;
	size_t rfind(const char* str, size_t idx=std::string::npos) const;
	size_t rfind(const char* str, size_t idx, size_t length) const;
	size_t rfind(char ch, size_t idx=std::string::npos) const;

	UString substr(size_t idx, size_t num = std::string::npos) const;



	size_t format(const char* fmt, ...);

	int icompare(const char* str) const;
	int icompare(const UString& other) const;

	UString&  toLower();
	UString&  toUpper();

	size_t remove(char ch);

	bool contains(char ch) const;
	bool contains(const char* str) const;
	bool contains(const char* str, size_t length) const;
	bool contains(const UString& other) const;

	bool startWith(char ch) const;
	bool startWith(const char* pattern) const;
	bool startWith(const char* pattern, size_t length) const;
	bool startWith(const UString& pattern) const;

	bool endWith(char ch) const;
	bool endWith(const char* pattern) const;
	bool endWith(const char* pattern, size_t length) const;
	bool endWith(const UString& pattern) const;

	UString&  trimLeft();
	UString&  trimLeft(char ch);
	UString&  trimLeft(const char* pattern);
	UString&  trimLeft(const char* pattern, size_t length);

	UString&  trimRight();
	UString&  trimRight(char ch);
	UString&  trimRight(const char* pattern);
	UString&  trimRight(const char* pattern, size_t length);

	UString&  trim();
	UString&  trim(const char* pattern);


	UString(const std::string& other):
			m_pimpl()
	{
		create();
		assign(other.c_str(), other.length());
	}

	inline UString& operator = (const std::string& str)
	{
		return assign(str.c_str(), str.length());
	}

	inline UString& assign(const std::string& other)
	{
		return assign(other.c_str(), other.length());
	}

	inline bool operator == (const std::string& other) const
	{
		return (*this) == other.c_str();
	}

	inline bool operator != (const std::string& other) const
	{
		return (*this) != other.c_str();
	}

	inline bool operator < (const std::string& other) const
	{
		return (*this) < other.c_str();
	}

	inline bool operator <= (const std::string& other) const
	{
		return (*this) <= other.c_str();
	}

	inline bool operator > (const std::string& other) const
	{
		return (*this) > other.c_str();
	}

	inline bool operator >= (const std::string& other) const
	{
		return (*this) >= other.c_str();
	}

	inline std::string toString() const
	{
		return std::string(c_str(), length());
	}

private:
	std::string& str();
	const std::string& str() const;

	void create();

private:
    UStringPrivate* m_pimpl;

};


inline std::ostream&  operator << (std::ostream& os, const UString& s)
{
    os << s.c_str();
    return os;
}



#endif /* USTRING_H_ */
